package main

import (
	"fmt"
	"sync"
	"time"
)

/**
设计一个任务调度器，接收一组任务（可以用函数表示），并使用协程并发执行这些任务，同时统计每个任务的执行时间。
*/

/**
1、定义一个Task结构体, Task结构体包含一个执行函数，taskId
2、定义任务调度器，调度器包含一个通道（队列），
3、定义若干个任务，放入调度器的队列中
*/

type Task struct {
	TaskId  int
	Execute func()
}

type Executor struct {
	queue  chan *Task
	worker int
	wg     sync.WaitGroup
}

func (Executor) newExecutor(worker, cap int) *Executor {
	return &Executor{
		make(chan *Task, cap),
		worker,
		sync.WaitGroup{},
	}
}

func (exe *Executor) addTask(task *Task) {
	exe.wg.Add(1)
	exe.queue <- task
}

func (exe *Executor) start() {
	for i := 0; i < exe.worker; i++ {
		go func() {
			//如果只有这一个，那么任务是串行的，如果要并行，这里需要变更成goroutine,并且开启多个goroutine
			for task := range exe.queue {
				fmt.Println("接收到task")
				task.Execute()
				exe.wg.Done()
			}
		}()
	}

}

func (exe *Executor) close() {
	close(exe.queue)
}

func (exe *Executor) wait() {
	exe.wg.Wait()
}

func main() {
	exe := new(Executor).newExecutor(3, 10)
	exe.start()

	exe.addTask(&Task{1, func() {
		time.Sleep(2 * time.Second)
		fmt.Println("任务一执行完毕。。。")
	}})
	exe.addTask(&Task{2, func() {
		time.Sleep(2 * time.Second)
		fmt.Println("任务二执行完毕。。。")
	}})
	exe.addTask(&Task{3, func() {
		time.Sleep(2 * time.Second)
		fmt.Println("任务三执行完毕。。。")
	}})

	defer exe.close()
	defer exe.wait()

}
